#include "ELShapeO.h"
#include <cstdlib>
#include <QTextStream>
#define elout(z) QTextStream out(stdout); out << z;
ELShapeO::ELShapeO(bool **tableState, QColor ***tableColors, int numBlockVertical, int numBlockHorizontal)
    : ELAbstractShape(tableState, tableColors, numBlockVertical, numBlockHorizontal)
{}

ELShapeO::~ELShapeO() {

}

// set left_, top_ of the shape.
bool ELShapeO::prepare() {
    switch (state) {
        case 0:
        case 1:
        case 2:
        case 3:
            /*
               00
               00
            */
            left_ = column / 2 - 2;
            top_ = row - 1;
            if (hasBlock[top_][left_ + 1] || hasBlock[top_][left_ + 2] ||
                hasBlock[top_ - 1][left_ + 1] || hasBlock[top_ - 1][left_ + 2]) {
                return false;
            }
            *colors[top_][left_ + 1] = blockColor;
            *colors[top_][left_ + 2] = blockColor;
            *colors[top_ - 1][left_ + 1] = blockColor;
            *colors[top_ - 1][left_ + 2] = blockColor;

            hasBlock[top_][left_ + 1] = true;
            hasBlock[top_][left_ + 2] = true;
            hasBlock[top_ - 1][left_ + 1] = true;
            hasBlock[top_ - 1][left_ + 2] = true;
            return true;
        default:
            break;
    }
    return false;
}

// clear current shape and draw it to its left_.
bool ELShapeO::moveLeft() {
    if (canMoveLeft()) {
        // move left_.
        *colors[top_][left_] = *colors[top_ - 1][left_] = blockColor;
        hasBlock[top_][left_] = hasBlock[top_ - 1][left_] = true;
        hasBlock[top_][left_ + 2] = hasBlock[top_ - 1][left_ + 2] = false;
        --left_;
        return true;
    }
    else {
        return false;
    }
}

// return true, if it can move left_.
bool ELShapeO::canMoveLeft() {
    return ((left_ + 1) > 0 && (!hasBlock[top_][left_] && !hasBlock[top_ - 1][left_]));
}

// clear current shape and draw it to its right.
bool ELShapeO::moveRight() {
    if (canMoveRight()) {
        // move right.
        hasBlock[top_][left_ + 1] = hasBlock[top_-1][left_ + 1] = false;
        hasBlock[top_][left_ + 3] = hasBlock[top_-1][left_ + 3] = true;
        *colors[top_][left_ + 3] = *colors[top_-1][left_ + 3] = blockColor;
        ++left_;
        return true;
    }
    else {
        return false;
    }
}

// return true, if it can move right.
bool ELShapeO::canMoveRight() {
    return ((left_ + 2) < (column - 1) && (!hasBlock[top_][left_ + 3] && !hasBlock[top_ - 1][left_ + 3]));
}

// clear current shape and draw it to its foot.
bool ELShapeO::moveDown() {
    if (canMoveDown()) {
        // move down.
        hasBlock[top_][left_ + 1] = hasBlock[top_][left_ + 2] = false;
        hasBlock[top_ - 2][left_ + 1] = hasBlock[top_ - 2][left_ + 2] = true;
        *colors[top_ - 2][left_ + 1] = *colors[top_ - 2][left_ + 2] = blockColor;
        --top_;
        return true;
    }
    else {
        return false;
    }
}

// return true, if it can move down.
bool ELShapeO::canMoveDown() {
    switch (state) {
        case 0:
        case 1:
        case 2:
        case 3:
            return ((top_ >  1) && (!hasBlock[top_ - 2][left_ + 1] && !hasBlock[top_ - 2][left_ + 2]));
        default:
            return false;
    }
    return false;
}

// clear current shape and draw it in its final locaiton.
void ELShapeO::moveToBottom() {
    // let if fall.
    while (canMoveDown()) {
        moveDown();
    }
}

// rotate the shape by 90, clockwise.
bool ELShapeO::rotate() {
    if (canRotate()) {
        // rotate.
        return true;
    }
    else {
        return false;
    }
}

// return true, if it can rotate.
bool ELShapeO::canRotate() {
    return false;
}

void ELShapeO::printTableState() {
    QTextStream out(stdout);
    for (int i=0; i<row; ++i) {
        for (int j=0; j<column; ++j) {
            out << hasBlock[i][j];
        }
        out << "\n";
    }
}

void ELShapeO::setLayout() {
    layout[0] = 5;
    layout[1] = 6;
    layout[2] = 9;
    layout[3] = 10;
}

void ELShapeO::setState(int newState) {
    state = newState;
    switch (state) {
        case 0:
        case 1:
        case 2:
        case 3:
            layout[0] = 5;
            layout[1] = 6;
            layout[2] = 9;
            layout[3] = 10;
            break;
        default:
            break;
    }
}

int ELShapeO::height() {
    return 2;
}

void ELShapeO::reset() {
    left_ = column / 2 - 2;
    top_ = row - 1;
}
